import asyncio
import websockets
import struct
import sys

# 定义玩家数量
player_num = int(sys.argv[1])
server_port = int(sys.argv[2])

# 用于存储未同步的数据，每个玩家对应一个元素
unsyncedData = [None] * player_num

# 防止同一个ip的多次请求
ip_set = set()

# 用于存储已同步的数据，每个玩家对应一个元素
syncedData = [None] * player_num

# 存储所有活跃的WebSocket连接
active_connections = set()
print('新房间已被创建')
# WebSocket服务器处理客户端连接的异步函数
async def echo(websocket):
    global unsyncedData, syncedData, ip_set
    address = websocket.remote_address[0] + ':' + str(websocket.remote_address[1])
    try:
        # 如果已满，不再接受连接
        if len(active_connections)==player_num:
            print('房间已满')
            return
        # 将新的连接添加到活跃连接集合中
        active_connections.add(websocket)
        # 异步接收客户端发送的数据
        async for data in websocket:
            # 从数据中解包玩家ID
            player_id = struct.unpack('i', data[:4])[0]
            if len(data)<10:
                # 如果没有分配id
                if player_id==-1:
                    # 获取ip和端口
                    if address in ip_set:
                        continue
                    print('玩家'+str(len(ip_set))+'加入房间,ip为'+address)
                    await websocket.send(struct.pack('i', len(ip_set)))
                    ip_set.add(address)
                    continue
                else:
                    if len(ip_set)==int(sys.argv[1]):
                        print('游戏开始')
                        await websocket.send(struct.pack('i',100))
                        continue
            else:
                # 正常游戏阶段
                # 存储除了玩家ID之外的数据
                unsyncedData[player_id] = data[4:]
                WinPlayerId=-1
                winFlag=False
                for i in range(player_num):
                    if int(data[46+i])!=0:
                        if WinPlayerId!=-1:
                            winFlag=False
                            break
                        else:
                            WinPlayerId=i
                            winFlag=True
                if winFlag and player_num>1:
                    print(WinPlayerId)
                    await websocket.send(struct.pack('i',WinPlayerId))
                    continue
                    

                # 如果还有未接收到的数据，则跳过当前循环
                if None in unsyncedData:
                    continue
                # 获取数据中的帧ID
                frame_id = data[4:8]

                # 标记是否所有玩家的数据都已同步
                sync_flag = True
                for eachData in unsyncedData:
                    # 如果数据帧ID不匹配，则标记为未同步
                    if eachData[:4] != frame_id:
                        sync_flag = False
                        break

                # 如果所有数据都已同步，则复制到syncedData
                if sync_flag:
                    syncedData = unsyncedData.copy()

                # 如果syncedData中还有未同步的数据，则跳过当前循环
                if None in syncedData:
                    continue

                # 将所有已同步的数据连接起来
                concatenated_data = b''.join(syncedData)
                # print(concatenated_data)
                # 此处应有发送数据到客户端的逻辑，这里只是打印出来
                await websocket.send(concatenated_data)
                
    except websockets.exceptions.ConnectionClosed:
        # 如果连接被关闭，打印消息
        print(f"连接已关闭，客户端IP和端口: {address}")
    finally:
        # 从活跃连接集合中移除连接
        active_connections.remove(websocket)
        print(websocket.remote_address[0] + ':' + str(websocket.remote_address[1]))
        # 如果没有活跃的连接，关闭服务器
        if not active_connections:
            print("所有连接都已断开，关闭服务器。")
            # 取消future以停止服务器
            future.cancel()

# 启动WebSocket服务器的异步函数
async def main():
    # 创建一个future对象，用于在需要时取消
    global future
    future = asyncio.Future()
    # 启动WebSocket服务器
    async with websockets.serve(echo, "0.0.0.0", server_port):
        # 等待future被取消
        await future

# 运行WebSocket服务器
asyncio.run(main())
